package com.ecarx.module_network.controller;

import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiNetworkSuggestion;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;


import com.ecarx.library_base.BaseApplication;
import com.ecarx.library_base.base_util.NotifyListener;
import com.ecarx.library_base.base_util.ThreadUtils;
import com.ecarx.library_base.base_widget.InputDialog;
import com.ecarx.module_network.bean.WifiInfo;
import com.ecarx.module_network.utils.WifiCallBack;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;


public class WifiController {
    private final WifiManager mWifiManager;
    private static volatile WifiController mWifiController;
    private final ConnectivityManager mConnManager;
    private Context mContext;
    private static final String AP_STATE_ACTION = "android.net.wifi.WIFI_AP_STATE_CHANGED";
    private static final String NETWORK_STATE = "android.net.conn.CONNECTIVITY_CHANGE";
    private static final String TAG = WifiController.class.getName();
    private List<WifiCallBack> mWifiCallBack = new ArrayList<>();
    boolean isInit = false;
    /**
     * 已经连接的wifi
     */
    public WifiInfo mConnectedWifiInfo;
    /**
     * 正在连接的wifi
     */
    private WifiInfo mConnectingWifiInfo;
    private static final String UNKNOWNSSID = "<unknown ssid>";

    private Handler mHandler;  //超时的handler
    private Scanner mScanner; //扫描的Handler
    /**
     * 连接wifi超时时间定为30秒
     */
    private static final int TIMEOUT_CONNECT_WIFI = 30 * 1000;


    /**
     * 连接是否已经超时，防止超时后收到连接失败的fwk回调导致提示重复，超时后不处理fwk的回调
     */
    boolean mConnectedTimeOut = false;

    /**
     * 是否进行了四次握手
     * ①有密码，密码正确，连接成功
     * ②有密码，密码错误，连接失败
     * 这2种情况下流程上都会走到FOUR_WAY_HANDSHAKE
     */
    private boolean HAS_FOUR_WAY_HANDSHAKE = false;

    private String mErrorConnoctingID;

    public void addWifiCallBack(WifiCallBack wifiCallBack) {
        mWifiCallBack.add(wifiCallBack);
    }

    public void removeWifiCallBack(WifiCallBack wifiCallBack) {
        mWifiCallBack.remove(wifiCallBack);
    }

    public static WifiController getInstance() {
        if (mWifiController == null) {
            synchronized (WifiController.class) {
                if (mWifiController == null) {
                    mWifiController = new WifiController();
                }
            }
        }
        return mWifiController;
    }

    private WifiController() {
        mContext = BaseApplication.getInstance();
        mWifiManager = (WifiManager) mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        mConnManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);

    }

    public void init() {
        if (isInit) {
            return;
        }
        isInit = true;
        final IntentFilter filter = new IntentFilter();
        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
        filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
        filter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
        filter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
        filter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);

        filter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
        filter.addAction("android.net.wifi.CONFIGURED_NETWORKS_CHANGE");
        filter.addAction("android.net.wifi.LINK_CONFIGURATION_CHANGED");

        filter.addAction(NETWORK_STATE);//增加network状态变更监听
        filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
        filter.addAction(AP_STATE_ACTION);
        mContext.registerReceiver(mReceiver, filter);
        mHandler = new Handler(Looper.getMainLooper()) {
            @SuppressLint("HandlerLeak")
            @Override
            public void handleMessage(@NonNull Message msg) {
                if (msg.what == TIMEOUT_CONNECT_WIFI) {
                    if (mWifiCallBack != null) {

                        Log.d(TAG, "handleMessage: TimeOut" + mConnectingWifiInfo);
                        if (getConnectingWifi() != null) {
                            ignore(getConnectingWifi().getSsid());
                            setConnectingWifi(null);
                        }
                        for (WifiCallBack callBack : mWifiCallBack) {
                            callBack.recWifiTimeOut();
                        }
                        mConnectedTimeOut = true;
                    }
                    mConnectingWifiInfo = null;
                }
                removeMessages(msg.what);
            }

        };
        if (mScanner == null) {
            mScanner = new Scanner();
        }
    }

    class Scanner extends Handler {
        private int mRetry = 0;

        void resume() {
            if (!this.hasMessages(0)) {
                this.sendEmptyMessage(0);
            }
        }

        void pause() {
            this.mRetry = 0;
            this.removeMessages(0);
        }

        @Override
        public void handleMessage(Message message) {
            if (message.what == 0) {
                //当作为热点有设备连接时,mWifiManager.startScan()方法很慢会阻塞主线程导致anr
                new Thread(() -> {
                    if (mWifiManager.startScan()) {
                        Scanner.this.mRetry = 0;
                    } else if (++Scanner.this.mRetry >= 3) {
                        Scanner.this.mRetry = 0;
                        return;
                    }
                    Scanner.this.removeMessages(0);
                    Scanner.this.sendEmptyMessageDelayed(0, 10000L);
                }).start();

            }
        }
    }


    public WifiInfo getConnectingWifi() {
        return mConnectingWifiInfo;
    }

    /**
     * 切换正在连接的wifi，断开上次wifi
     */

    public void setConnectingWifi(WifiInfo wifi) {
        if (wifi != null) {
            wifi.setConnecting(true);
        }
        mConnectingWifiInfo = wifi;
    }

    public boolean isWifiEnable() {
        return mWifiManager.isWifiEnabled();
    }

    public boolean setWifiEnable(boolean isEnable) {
        boolean b = mWifiManager.setWifiEnabled(isEnable);
        return b;
    }


    public WifiInfo getConnectWifi() {
        return mConnectedWifiInfo;
    }

    public void release() {
        isInit = false;
        if (mReceiver != null) {
            mContext.unregisterReceiver(mReceiver);
        }
        if (mHandler != null) {
            mHandler.removeMessages(TIMEOUT_CONNECT_WIFI);
        }
        if (mScanner != null) {
            mScanner.pause();
        }

    }

    /**
     * 得到wifi的状态
     */
    public OpenState getWifiState() {
        OpenState mWifiOpenState;
        if (mWifiManager.isWifiEnabled()) {
            if (setConnectedWifi()) {
                mWifiOpenState = OpenState.COLLECTED;
            } else {
                mWifiOpenState = OpenState.OPEN;
            }
        } else {
            mWifiOpenState = OpenState.CLOSE;
        }
        return mWifiOpenState;
    }


    public BroadcastReceiver mReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
//            Log.i(TAG, "onReceive-" + action);
            if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {  //Wifi开关发生变化
                final int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0);
                recWifiStatus(wifiState);

            } else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action) || "android.net.wifi.CONFIGURED_NETWORKS_CHANGE".equals(action) || "android.net.wifi.LINK_CONFIGURATION_CHANGED".equals(action)) {
                //wifi扫描完成
//                Log.i(TAG, "onReceive-SCAN_RESULTS_AVAILABLE_ACTION==" + action);
                for (WifiCallBack callBack : mWifiCallBack) {
                    mHandler.post(() -> callBack.recRefreshWifiInfo());

                }
            } else if (WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(action)) {
                final SupplicantState state = intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE);
                recSupplicantStatus(intent, state); //密码错误
            } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
                final NetworkInfo networkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
                android.net.wifi.WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
                recNetworkState(networkInfo, wifiInfo); //连接成功
                Log.i(TAG, "onReceive-NETWORK_STATE_CHANGED_ACTION" + wifiInfo);

            } else if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {
                Log.i(TAG, "onReceive-RSSI_CHANGED_ACTION");//信号强度发生变化
                for (WifiCallBack callBack : mWifiCallBack) {
                    callBack.recWifiSignalChanged();
                }
            } else if (NETWORK_STATE.equals(action)) {
                //network状态变更也检查wifi连接情况
                final NetworkInfo networkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
                recNetworkState(networkInfo, mWifiManager.getConnectionInfo());
                Log.i(TAG, "onReceive-CONNECTIVITY_CHANGE" + networkInfo);
            } else if (AP_STATE_ACTION.equals(action)) {
                int state = intent.getIntExtra("wifi_state", 0);
                if (state == 13) {
                    mWifiCallBack.stream().forEach(wifiCallBack -> wifiCallBack.switchWifiOpen());
                }
            }
        }

    };

    /**
     * 连接成功或断开连接
     *
     * @param networkInfo
     * @param wifiInfo
     */
    private void recNetworkState(NetworkInfo networkInfo, android.net.wifi.WifiInfo wifiInfo) {

        // 网络连接成功
        if (networkInfo.getDetailedState() == NetworkInfo.DetailedState.CONNECTED) {
            Log.i(TAG, "recNetworkState-connect = " + wifiInfo);
            if (mWifiCallBack != null && wifiInfo != null) {
                if (!TextUtils.isEmpty(wifiInfo.getSSID()) && !UNKNOWNSSID.equals(wifiInfo.getSSID())) {
                    if (mHandler != null) {
                        mHandler.removeMessages(TIMEOUT_CONNECT_WIFI);
                    }
                    for (WifiCallBack callBack : mWifiCallBack) {
                        callBack.recWifiConnectSuccess(removeDoubleQuotes(wifiInfo.getSSID()), wifiInfo);
                    }
                    setConnectingWifi(null);
                }
            }

        } else if (networkInfo.getDetailedState() == NetworkInfo.DetailedState.DISCONNECTED) {
            Log.i(TAG, "recNetworkState-disconnect" + wifiInfo);
            if (mWifiCallBack != null) {
                for (WifiCallBack callBack : mWifiCallBack) {
                    callBack.recWifiDisConnectSuccess();
                }
            }
        }
    }

    private void recWifiStatus(int wifiState) {
        Log.i(TAG, "recWifiStatus[" + wifiState + "]");
        switch (wifiState) {
            case WifiManager.WIFI_STATE_DISABLED:
                Log.i(TAG, "recWifiStatus-WIFI_STATE_DISABLED");
                if (mWifiCallBack != null) {
                    for (WifiCallBack callBack : mWifiCallBack) {
                        callBack.recWifiState(OpenState.CLOSE);
                    }
                }
                mScanner.pause();
                break;
            case WifiManager.WIFI_STATE_ENABLED:
                Log.i(TAG, "recWifiStatus-WIFI_STATE_ENABLED");
                if (mWifiCallBack != null) {
                    for (WifiCallBack callBack : mWifiCallBack) {
                        callBack.recWifiState(OpenState.OPEN);
                    }
                    startScan();
                }
                break;
            default:
                break;
        }
    }


    private void recSupplicantStatus(Intent intent, SupplicantState state) {
        final boolean hasErrorCode = intent.hasExtra(WifiManager.EXTRA_SUPPLICANT_ERROR);
        Log.e(TAG, "recSupplicantStatus state:" + state + ",hasErrorCode:" + hasErrorCode);

        if (SupplicantState.SCANNING.equals(state))// 扫描网络
        {
            Log.i(TAG, "recSupplicantStatus-SCANNING");

        } else if (SupplicantState.DISCONNECTED.equals(state)) {
            Log.i(TAG, "recSupplicantStatus-DISCONNECTED==wifiinfo");


        } else if (SupplicantState.INACTIVE.equals(state)) {
            Log.i(TAG, "recSupplicantStatus-INACTIVE");
        } else if (SupplicantState.ASSOCIATING.equals(state))// 开始配对
        {
            Log.i(TAG, "recSupplicantStatus-ASSOCIATING");
            HAS_FOUR_WAY_HANDSHAKE = false;
            mErrorConnoctingID = "";
        } else if (SupplicantState.ASSOCIATED.equals(state))// 配对成功
        {
            Log.i(TAG, "recSupplicantStatus-ASSOCIATED");
        } else if (SupplicantState.FOUR_WAY_HANDSHAKE.equals(state))// 四次握手
        {
            Log.i(TAG, "recSupplicantStatus-FOUR_WAY_HANDSHAKE==" + mWifiManager.getConnectionInfo());
            mErrorConnoctingID = removeDoubleQuotes(mWifiManager.getConnectionInfo().getSSID());
            HAS_FOUR_WAY_HANDSHAKE = true;
        } else if (SupplicantState.GROUP_HANDSHAKE.equals(state)) {
            Log.i(TAG, "recSupplicantStatus-GROUP_HANDSHAKE");
        } else if (SupplicantState.COMPLETED.equals(state)) {
            Log.i(TAG, "recSupplicantStatus-COMPLETED");
        }
        /**
         * isShowError表示是否在wifi列表页面，hasErrorCode表示是否是密码错误
         */
        if (hasErrorCode) {
            final int errorCode = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, 0);
            Log.d(TAG, "recSupplicantStatus-hasErrorCode=" + errorCode + ";HAS_FOUR_WAY_HANDSHAKE=" + HAS_FOUR_WAY_HANDSHAKE);
            if (errorCode == WifiManager.ERROR_AUTHENTICATING && HAS_FOUR_WAY_HANDSHAKE) {
                if (mHandler != null) {
                    mHandler.removeMessages(TIMEOUT_CONNECT_WIFI);
                }
                setConnectingWifi(null);
                ignore(mErrorConnoctingID);
                // 密码错误
                for (WifiCallBack callBack : mWifiCallBack) {
                    callBack.recWifiConnectFailure(mErrorConnoctingID);
                }
            }
        }
    }


    public void ignore(String ssid) {
        getExitWifi(ssid, (result, data) -> {
            if (result != null) {
                WifiNetworkSuggestion wifiNetworkSuggestion = (WifiNetworkSuggestion) result;
                Log.d(TAG, "ignore: name=" + wifiNetworkSuggestion.getSsid());
                List<WifiNetworkSuggestion> wifiNetworkSuggestions = new ArrayList<>();
                wifiNetworkSuggestions.add(wifiNetworkSuggestion);
                mWifiManager.removeNetworkSuggestions(wifiNetworkSuggestions);
            }
        });
    }


    public void disconnect(WifiInfo wifiInfo) {
        if (wifiInfo == null || TextUtils.isEmpty(wifiInfo.getSsid())) {
            return;
        }
        Log.d(TAG, "ignore: disconnect");
        ignore(wifiInfo.getSsid());

    }


    /**
     * 获取所有扫描到的网络列表，包含正在连接的网络，不包含已经连接的网络
     *
     * @return 所有扫描列表
     */
    public List<WifiInfo> getAllWifiInfo() {

        final List<ScanResult> results = mWifiManager.getScanResults();
        //比较重复ssid,取信号大的一个
        HashMap<String, WifiInfo> dup = new HashMap<>();
        WifiInfo wifiInfo = null;
        if (results != null && mConnManager != null) {
            for (ScanResult result : results) {
                // Ignore hidden and ad-hoc networks.
                if (TextUtils.isEmpty(result.SSID) || result.capabilities.contains("[IBSS]")) {
                    continue;
                }
                if (mConnectedWifiInfo != null && mConnectedWifiInfo.getSsid().equals(result.SSID)) {
                    mConnectedWifiInfo.setLevel(result.level);
                    mConnectedWifiInfo.setCapabilities(result.capabilities);
                    continue;
                }
                if (dup.get(result.SSID) == null) {
                    wifiInfo = getWifiInfo(result);
                } else {
                    wifiInfo = getWifiInfo(result);
                    wifiInfo = handleApLevel(dup.get(result.SSID), wifiInfo);
                }
                if (mConnectingWifiInfo != null && mConnectingWifiInfo.getSsid().equals(wifiInfo.getSsid())) {
                    wifiInfo.setConnecting(mConnectingWifiInfo.isConnecting());
                    mConnectingWifiInfo = wifiInfo;
                }
                dup.put(result.SSID, wifiInfo);
            }
        }
        List<WifiInfo> infos = new ArrayList<>(dup.values());
        Collections.sort(infos);
        Log.i(TAG, "getAllWifiInfo " + infos.size());

        return infos;
    }

    private WifiInfo getWifiInfo(ScanResult result) {
        WifiInfo wifiInfo;
        wifiInfo = new WifiInfo(WifiInfo.Type.SCAN);
        wifiInfo.setSsid(result.SSID);
        wifiInfo.setBssid(result.BSSID);
        wifiInfo.setLevel(result.level);
        wifiInfo.setCapabilities(result.capabilities);

        return wifiInfo;
    }


    /**
     * 获取可用网络，历史记录网络列表
     */
    public List<WifiInfo> getAllList() {
        List<WifiInfo> allData = getAllWifiInfo();
        ArrayList<WifiInfo> exist = new ArrayList<>();
        for (WifiInfo item : allData) {
            if (mConnectingWifiInfo != null && mConnectingWifiInfo.isConnecting()) {
                if (item.getSsid().equals(mConnectingWifiInfo.getSsid())) {
                    exist.add(0, mConnectingWifiInfo);
                    mConnectingWifiInfo.setConnectState(WifiInfo.ConnectState.CONNECTING);
                    continue;
                }
            }
            exist.add(item);
            item.setConnectState(WifiInfo.ConnectState.DISCONNECTED);

        }
        allData.clear();
        allData.addAll(exist);
        return allData;
    }


    /**
     * 比较返回信号最强的wifi
     *
     * @return
     */
    private WifiInfo handleApLevel(WifiInfo last, WifiInfo cur) {
        return (WifiManager.compareSignalLevel(last.getLevel(), cur.getLevel()) >= 0) ? last : cur;
    }

    /**
     * 设置当前连接成功的wifi
     *
     * @return
     */
    public boolean setConnectedWifi() {
        final android.net.wifi.WifiInfo wifiInfo = mWifiManager.getConnectionInfo();

        if (wifiInfo != null && !TextUtils.isEmpty(wifiInfo.getSSID())) {
            final SupplicantState mSupplicantState = wifiInfo.getSupplicantState();
            if (mSupplicantState == SupplicantState.COMPLETED && !UNKNOWNSSID.equals(wifiInfo.getSSID())) {
                if (mConnectedWifiInfo == null) {
                    mConnectedWifiInfo = new WifiInfo();
                }
                mConnectedWifiInfo.setSsid(removeDoubleQuotes(wifiInfo.getSSID()));
                mConnectedWifiInfo.setBssid(wifiInfo.getBSSID());
                return true;

            } else {
                mConnectedWifiInfo = null;
            }
        } else {
            mConnectedWifiInfo = null;
        }
        return false;
    }


    /**
     * 4.0的连接的方法
     *
     * @param ssid     ssid
     * @param pswd     密码
     * @param security 方式
     */
    public void connect(final String ssid, final String pswd, final int security) {
        Log.i(TAG, "connect-1ssid" + ssid + ";pswd=" + pswd + ";security=" + security);
        getConfig(ssid, pswd, security, (result, data) -> {
            final WifiConfiguration config = (WifiConfiguration) result;
            if (config != null) {
                saveWifi(config);
                connectHideApi(config);
            }
        });
        mHandler.removeMessages(TIMEOUT_CONNECT_WIFI);
        mHandler.sendEmptyMessageDelayed(TIMEOUT_CONNECT_WIFI, TIMEOUT_CONNECT_WIFI);
        mConnectedTimeOut = false;
    }

    //通过ssid获取wifi配置
    public void getConfig(String ssid, String pswd, int security, NotifyListener listener) {
        getExitWifi(ssid, (result, data) -> {
            if (result != null) {
                WifiNetworkSuggestion tempConfig = (WifiNetworkSuggestion) result;
                List<WifiNetworkSuggestion> list = new ArrayList<>();
                list.add(tempConfig);
                mWifiManager.removeNetworkSuggestions(list);
            }
            WifiConfiguration config = new WifiConfiguration();
            config.SSID = "\"" + ssid + "\"";
            config.hiddenSSID = true;
            switch (security) {
                case WifiInfo.Security.NONE:
                    config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
                    break;
                case WifiInfo.Security.WEP:
                    config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
                    if (!TextUtils.isEmpty(pswd)) {
                        int length = pswd.length();
                        String password = pswd;
                        // WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
                        if ((length == 10 || length == 26 || length == 58) && password.matches("[0-9A-Fa-f]*")) {
                            config.wepKeys[0] = password;
                        } else {
                            config.wepKeys[0] = '"' + password + '"';
                        }
                    }
                    break;
                case WifiInfo.Security.PSK:
                    // config.allowedAuthALogorithms.set(AuthALogorithm.OPEN);
                    config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
                    if (!TextUtils.isEmpty(pswd)) {
                        String password = pswd;
                        if (password.matches("[0-9A-Fa-f]{64}")) {
                            config.preSharedKey = password;
                        } else {
                            config.preSharedKey = '"' + password + '"';
                        }
                    }
                    break;
                case WifiInfo.Security.EAP:
                    config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
                    config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
                    break;
                default:
                    config = null;
            }
            // config.proxySettings = ProxySettings.NONE;// 代理设置
            if (config != null) {
                config.priority = 2;
                config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
                config.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
            }
            listener.onNotify(config, config);
        });


    }

    /**
     * 是否存在ssid信息
     *
     * @param ssid
     * @return
     */
    public void getExitWifi(final String ssid, NotifyListener l) {
        ThreadUtils.getCachedPool().execute(() -> {
            String newSsid = ssid;
            if (ssid.startsWith("\"") && ssid.endsWith("\"")) {
                newSsid = ssid.substring(1, ssid.length() - 1);
            }
            Log.d(TAG, "getExitWifi: ssid=" + newSsid);
            WifiNetworkSuggestion suggestion = null;
            List<WifiNetworkSuggestion> existingConfigs = mWifiManager.getNetworkSuggestions();
            Log.d(TAG, "getExitWifi: existingConfigs.size=" + existingConfigs.size());
            if (existingConfigs != null && existingConfigs.size() > 0) {
                for (WifiNetworkSuggestion existingConfig : existingConfigs) {
                    Log.d(TAG, "getExitWifi: WifiNetworkSuggestion ssid=" + existingConfig.getSsid());
                    if (existingConfig.getSsid().equals("\"" + newSsid + "\"")) {
                        suggestion = existingConfig;
                        break;
                    }
                }
            }
            WifiNetworkSuggestion finalSuggestion = suggestion;
            l.onNotify(finalSuggestion, finalSuggestion);
        });
    }


    public void resetConnectWifi() {
        mConnectedWifiInfo = null;
    }


    /**
     * 有记录信息连接方式
     *
     * @param config
     */
    public void connect(WifiConfiguration config) {
        saveWifi(config);
        mHandler.removeMessages(TIMEOUT_CONNECT_WIFI);
        mHandler.sendEmptyMessageDelayed(TIMEOUT_CONNECT_WIFI, TIMEOUT_CONNECT_WIFI);
        mConnectedTimeOut = false;
        connectHideApi(config);
    }

    public WifiConfiguration wifiSuggestToConfig(WifiNetworkSuggestion suggestion) {
        WifiConfiguration config = new WifiConfiguration();
        config.SSID = suggestion.getSsid();
        config.preSharedKey = suggestion.getPassphrase();
        config.hiddenSSID = suggestion.isHiddenSsid();
        config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
        config.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
        return config;
    }


    public void startScan() {
        if (mScanner == null) {
            mScanner = new Scanner();
        }
        mScanner.resume();
    }


    /**
     * 去除引号
     * 4.0之后获取的名称包含有双引号
     */
    public static String removeDoubleQuotes(String string) {
        int length = string.length();
        if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) {
            return string.substring(1, length - 1);
        }
        return string;
    }

    /**
     * 获取wifi类型
     *
     * @param config
     * @return
     */
    public static int getSecurity(WifiConfiguration config) {
        if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
            return WifiInfo.Security.PSK;
        }
        if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP) || config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)) {
            return WifiInfo.Security.EAP;
        }
        return WifiInfo.Security.NONE;
    }

    public static boolean isWifiApOpen(Context context) {
        try {
            WifiManager manager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            //通过放射获取 getWifiApState()方法
            Method method = manager.getClass().getDeclaredMethod("getWifiApState");
            //调用getWifiApState() ，获取返回值
            int state = (int) method.invoke(manager);
            //通过放射获取 WIFI_AP的开启状态属性
            Field field = manager.getClass().getDeclaredField("WIFI_AP_STATE_ENABLED");
            //获取属性值
            int value = (int) field.get(manager);
            //判断是否开启
            if (state == value) {
                return true;
            } else {
                return false;
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return false;
    }


    private void connectHideApi(WifiConfiguration configuration) {
        try {
            Class<?> cls = Class.forName("android.net.wifi.WifiManager");
            Class<?> apListenerClass = Class.forName("android.net.wifi.WifiManager$ActionListener");
            Method m = cls.getDeclaredMethod("connect", WifiConfiguration.class, apListenerClass);
            m.invoke(mWifiManager, configuration, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void saveWifi(WifiConfiguration configuration) {
        Log.d(TAG, "saveWifi: ssid=" + configuration.SSID);
        getExitWifi(configuration.SSID, (result, data) -> {
            if (result != null) {
                WifiNetworkSuggestion exsits = (WifiNetworkSuggestion) result;
                List<WifiNetworkSuggestion> lists = new ArrayList<>();
                lists.add(exsits);
                mWifiManager.removeNetworkSuggestions(lists);
            }
            WifiNetworkSuggestion.Builder builder = new WifiNetworkSuggestion.Builder();
            if (!TextUtils.isEmpty(configuration.preSharedKey)) {
                builder.setWpa2Passphrase(configuration.preSharedKey);
            }
            WifiNetworkSuggestion wifiNetworkSuggestion = builder.setSsid(configuration.SSID).setIsAppInteractionRequired(true).build();

            List<WifiNetworkSuggestion> lists = new ArrayList<>();
            lists.add(wifiNetworkSuggestion);
            mWifiManager.addNetworkSuggestions(lists);
        });


    }

    public void onClickConnectWifi(WifiInfo wifiInfo) {
        if (getConnectWifi() == wifiInfo) {
            return;
        }
        final String ssid = wifiInfo.getSsid();
        final int security = wifiInfo.getSecurity();
        /**
         * 取消上一次连接的信息
         */
        if (getConnectingWifi() != null) {
            getConnectingWifi().setConnecting(false);
            disconnect(getConnectingWifi());
        }
        /**
         * 正在连接
         */
        if (!TextUtils.isEmpty(wifiInfo.getPassword()) || security == WifiInfo.Security.NONE) {
            mWifiCallBack.stream().forEach(c -> c.recWifiDisConnectSuccess());
            setConnectingWifi(wifiInfo);
            getConnectingWifi().setConnecting(true);
            mWifiCallBack.stream().forEach(c -> c.recRefreshWifiInfo());
            connect(ssid, wifiInfo.getPassword(), security);
        } else {
            getExitWifi(wifiInfo.getSsid(), (result, data) -> {
                ThreadUtils.runOnUiThread(() -> {

                    if (result != null) {
                        mWifiCallBack.stream().forEach(c -> c.recWifiDisConnectSuccess());
                        setConnectingWifi(wifiInfo);
                        final WifiNetworkSuggestion config = (WifiNetworkSuggestion) result;
                        connect(wifiSuggestToConfig(config));
                        mWifiCallBack.stream().forEach(c -> c.recRefreshWifiInfo());
                    } else {
                        mWifiCallBack.stream().forEach(c -> c.recEncryptWifi(wifiInfo));

                    }
                });
            });

        }
    }

    public enum OpenState {
        OPEN, CLOSE, COLLECTED
    }

}
